/* fun list
 * apleilx
 * @ 20210412
 */

#ifndef __FUN_LIST_H__
#define __FUN_LIST_H__

#include "sys_init.h"

/*****************************************************************************
 * @brief   函数指针定义
 *****************************************************************************/
#define FUN_LIST_ADD_OBJ(list, fn, lev)                    \
    extern void fn(void);                                  \
    extern const char list##_fun_flag;                     \
    char fun_list_check_##fn() { return list##_fun_flag; } \
    OBJ_USED const sys_init_fn __fun_ptr_##fn OBJ_SECTION("__fun_list_" #list "_" lev) = fn

#define FUN_LIST_EXPORT(list, fn) FUN_LIST_ADD_OBJ(list, fn, "2.app")

/*****************************************************************************
 * @brief   创建列表信息及主要函数
 *****************************************************************************/
#define FUN_LIST_CREAT(list)                                           \
    const char list##_fun_flag = 0;                                    \
    static void list##_head(void) {}                                   \
    static void list##_tail(void) {}                                   \
    OBJ_WEAK void list##_list_hook(void) {}                            \
                                                                       \
    FUN_LIST_ADD_OBJ(list, list##_head, "1.head");                     \
    FUN_LIST_ADD_OBJ(list, list##_tail, "3.tail");                     \
    FUN_LIST_ADD_OBJ(list, list##_list_hook, "ref.hook");              \
                                                                       \
    void list##_list_run_once(void)                                    \
    {                                                                  \
        volatile const sys_init_fn *fn_ptr = &__fun_ptr_##list##_head; \
        for (fn_ptr++; fn_ptr < &__fun_ptr_##list##_tail; fn_ptr++)    \
        {                                                              \
            (*fn_ptr)();                                               \
            list##_list_hook();                                        \
        }                                                              \
    }                                                                  \
                                                                       \
    void list##_list_run(void)                                         \
    {                                                                  \
        for (;;)                                                       \
            list##_list_run_once();                                    \
    }                                                                  \
                                                                       \
    void list##_list_run_once_pure(void)                               \
    {                                                                  \
        volatile const sys_init_fn *fn_ptr = &__fun_ptr_##list##_head; \
        for (fn_ptr++; fn_ptr < &__fun_ptr_##list##_tail; fn_ptr++)    \
            (*fn_ptr)();                                               \
    }                                                                  \
                                                                       \
    void list##_list_run_pure(void)                                    \
    {                                                                  \
        for (;;)                                                       \
            list##_list_run_once_pure();                               \
    }
/*****************************************************************************
 * @brief   外部hook定义
 *****************************************************************************/
#define fun_list_hook(list) void list##_list_hook(void)

/*****************************************************************************
 * @brief   ref
 *****************************************************************************/
#define FUN_LIST_REF(list)                \
    void list##_list_run(void);           \
    void list##_list_run_once(void);      \
    void list##_list_run_once_pure(void); \
    void list##_list_run_pure(void);

/*****************************************************************************
 * @brief   api
 *****************************************************************************/
#define fun_list_run(list) list##_list_run()                     //列表循环运行-列表+hook
#define fun_list_run_once(list) list##_list_run_once()           //列表运行一次-列表+hook
#define fun_list_run_pure(list) list##_list_run_pure()           //列表循环运行-纯列表，无hook
#define fun_list_run_once_pure(list) list##_list_run_once_pure() //列表运行一次-纯列表，无hook

#endif
